from mytools import bytes2int,int2bytes
import math
# 位图文件头
class BitmapFileHeader(object):
    def __init__(self,pic):
        super().__init__(pic)
        print("init BitmapFileHeader")
        pic.seek(0)
        self.bfType = pic.read(2)
        if self.bfType != b'BM':
            raise Exception ("This is not BMP file")
        self.bfSize = pic.read(4)
        self.bfReserved1 = pic.read(2)
        self.bfReserved2 = pic.read(2)
        self.bfOffBits = pic.read(4)
        BitmapFileHeader.updateInt(self) #notice
        """------------------------------------"""
    def updateInt(self):
        self.type=bytes2int(self.bfType)
        self.size=bytes2int(self.bfSize)
        self.reserved1=bytes2int(self.bfReserved1)
        self.reserved2=bytes2int(self.bfReserved2)
        self.offBits=bytes2int(self.bfOffBits)

    def updateBytes(self):
        self.bfSize=int2bytes(self.size,4)
        self.bfOffBits=int2bytes(self.offBits,4)

class DIB(object):#bitmap infomation header
    def __init__(self, pic):
        super().__init__()
        print("init DIB")
        pic.seek(14) 
        self.biSize = pic.read(4)
        self.biWidth = pic.read(4) #pixel
        self.biHeight = pic.read(4) #pixel
        self.biPlanes = pic.read(2)
        self.biBitCount = pic.read(2) #色深
        self.biCompression = pic.read(4)
        self.biSizeImage = pic.read(4)
        self.biXPelsPerMeter = pic.read(4)
        self.biYPelsPerMeter = pic.read(4)
        self.biClrUsed = pic.read(4)
        self.biClrImportant =  pic.read(4)
        DIB.updateInt(self) #notice

        """------------------------------------"""
    def updateBytes(self):
        self.biWidth=int2bytes(self.width,4)
        self.biHeight=int2bytes(self.height,4)
        self.biBitCount=int2bytes(self.bit_count,2)
        self.biSizeImage=int2bytes(self.size_image,4)
        self.biXPelsPerMeter=int2bytes(self.x_PelsPerMeter,4)
        self.biYPelsPerMeter=int2bytes(self.y_PelsPerMeter,4)

    def updateInt(self):
        self.head_size=bytes2int(self.biSize)
        self.width =bytes2int(self.biWidth)
        self.height =bytes2int(self.biHeight)
        self.planes =bytes2int(self.biPlanes)
        self.bit_count =bytes2int(self.biBitCount)
        self.compression =bytes2int(self.biCompression)
        self.size_image =bytes2int(self.biSizeImage)
        self.x_PelsPerMeter =bytes2int(self.biXPelsPerMeter)
        self.y_PelsPerMeter =bytes2int(self.biYPelsPerMeter)
        self.clr_used =bytes2int(self.biClrUsed)
        self.clr_important=bytes2int(self.biClrImportant)

class BmpData(BitmapFileHeader,DIB):
    def __init__(self,pic):
        '''应该也是一个好选择'''
        # BitmapFileHeader.__init__(self,pic)
        # DIB.__init__(self,pic)

        #这个模块的定位是做一些准备工作
        super(BmpData,self).__init__(pic)
        super(BitmapFileHeader,self).__init__(pic)

        self.pic=pic
        self.padding_num=self.update_padding_num()
        self.data=[]



    #更新int型属性
    def updateInt(self):
        BitmapFileHeader.updateInt(self)
        DIB.updateInt(self)
    def updateBytes(self):
        BitmapFileHeader.updateBytes(self)
        DIB.updateBytes(self)

    # 读入24位图的像素数据
    def parse_24(self):
        self.pic.seek(self.offBits)
        for row in range(self.height):
            row=[]
            for col in range(self.width):
                unit=[]
                for channel in range(3):
                    unit.append(self.pic.read(1))
                row.append(unit)
            self.data.append(row)
            self.pic.seek(self.padding_num,1)

    # 读入8位图的像素数据
    def parse_8(self):
        self.pic.seek(self.offBits)
        for y in range(self.height):
            row=[]
            for x in range(self.width):
                row.append(self.pic.read(1))
            self.data.append(row)


    # 我是想搞成类似c++中的拷贝构造函数，只复制对方的位图属性，不复制他的像素数据
    def copy(self,bmp):
        self.bfType=bmp.bfType
        self.bfSize=bmp.bfSize
        self.bfReserved1=bmp.bfReserved1
        self.bfReserved2=bmp.bfReserved2
        self.bfOffBits=bmp.bfOffBits
        self.biSize=bmp.biSize
        self.biWidth=bmp.biWidth
        self.biHeight=bmp.biHeight
        self.biPlanes=bmp.biPlanes
        self.biBitCount=bmp.biBitCount
        self.biCompression=bmp.biCompression
        self.biSizeImage=bmp.biSizeImage
        self.biXPelsPerMeter=bmp.biXPelsPerMeter
        self.biYPelsPerMeter=bmp.biYPelsPerMeter
        self.biClrUsed=bmp.biClrUsed
        self.biClrImportant=bmp.biClrImportant

        self.updateInt()

    # 更新每行需要填充的字节数
    def update_padding_num(self):
        # self.padding_num=self.width*3%4
        # if self.padding_num!=0:
        #     self.padding_num=4-self.padding_num
        
        # 写成这种形式只是显得很 pythonic
        padding_for_4=lambda n: math.ceil(n/4)*4-n
        if self.bit_count==24:
            self.padding_num = padding_for_4(self.width*3)
        elif self.bit_count==8:
            self.padding_num = padding_for_4(self.width)
        return self.padding_num

    def update_file_size(self):
        self.size_image = self.offBits + (self.width+self.padding_num)*self.height*self.bit_count
        self.size=self.size_image+self.offBits


if __name__ == '__main__':
    pic=open('res/256128b.bmp','rb')
    bmp=BmpData(pic)
